package ntu.p2p.dht;

import ntu.p2p.dht.messaging.DHTDifferenceDeserializer;
import ntu.p2p.dht.messaging.DHTUpdateObjectMessage;
import rice.Continuation;
import rice.environment.Environment;
import rice.p2p.commonapi.Endpoint;
import rice.p2p.commonapi.NodeHandle;

public interface DHT {

	/**
	 * Inserts an object with the given ID into this instance of Past.
	 * Asynchronously returns a PastException to command, if the operation was
	 * unsuccessful. If the operation was successful, a Boolean[] is returned
	 * representing the responses from each of the replicas which inserted the
	 * object.
	 * 
	 * @param obj
	 *          the object to be inserted
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void insert(DHTContent obj, Continuation<Boolean[], Exception> command);

	/**
	 * Retrieves the object stored in this instance of Past with the given ID.
	 * Asynchronously returns a PastContent object as the result to the provided
	 * Continuation, or a PastException. This method is provided for convenience;
	 * its effect is identical to a lookupHandles() and a subsequent fetch() to
	 * the handle that is nearest in the network.
	 * 
	 * The client must authenticate the object. In case of failure, an alternate
	 * replica of the object can be obtained via lookupHandles() and fetch().
	 * 
	 * This method is not safe if the object is immutable and storage nodes are
	 * not trusted. In this case, clients should used the lookUpHandles method to
	 * obtains the handles of all primary replicas and determine which replica is
	 * fresh in an application-specific manner.
	 * 
	 * By default, this method attempts to cache the result locally for future
	 * use. Applications which do not desire this behavior should use the
	 * lookup(id, boolean, command) method.
	 * 
	 * @param id
	 *          the key to be queried
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void lookup(DHTContentKey key, Continuation<DHTContent, Exception> command);

	/**
	 * Retrieves the object stored in this instance of Past with the given ID.
	 * Asynchronously returns a PastContent object as the result to the provided
	 * Continuation, or a PastException. This method is provided for convenience;
	 * its effect is identical to a lookupHandles() and a subsequent fetch() to
	 * the handle that is nearest in the network.
	 * 
	 * The client must authenticate the object. In case of failure, an alternate
	 * replica of the object can be obtained via lookupHandles() and fetch().
	 * 
	 * This method is not safe if the object is immutable and storage nodes are
	 * not trusted. In this case, clients should used the lookUpHandles method to
	 * obtains the handles of all primary replicas and determine which replica is
	 * fresh in an application-specific manner.
	 * 
	 * This method also allows applications to specify if the result should be
	 * cached locally.
	 * 
	 * @param id
	 *          the key to be queried
	 * @param cache
	 *          Whether or not the result should be cached
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void lookup(DHTContentKey key, boolean cache, Continuation command);

	/**
	 * Retrieves the handles of up to max replicas of the object stored in this
	 * instance of Past with the given ID. Asynchronously returns an array of
	 * PastContentHandles as the result to the provided Continuation, or a
	 * PastException.
	 * 
	 * Each replica handle is obtained from a different primary storage root for
	 * the the given key. If max exceeds the replication factor r of this Past
	 * instance, only r replicas are returned.
	 * 
	 * This method will return a PastContentHandle[] array containing all of the
	 * handles.
	 * 
	 * @param id
	 *          the key to be queried
	 * @param max
	 *          the maximal number of replicas requested
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void lookupHandles(DHTContentKey key, int max, Continuation command);

	/**
	 * Retrieves the handle for the given object stored on the requested node.
	 * Asynchronously returns a PostContentHandle (or null) to the provided
	 * continuation.
	 * 
	 * @param id
	 *          the key to be queried
	 * @param handle
	 *          The node on which the handle is requested
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void lookupHandle(DHTContentKey key, NodeHandle handle, Continuation command);

	/**
	 * Retrieves the object associated with a given content handle. Asynchronously
	 * returns a PastContent object as the result to the provided Continuation, or
	 * a PastException.
	 * 
	 * The client must authenticate the object. In case of failure, an alternate
	 * replica can be obtained using a different handle obtained via
	 * lookupHandles().
	 * 
	 * @param handle
	 *          the key to be queried
	 * @param command
	 *          Command to be performed when the result is received
	 */
	public void fetch(DHTContentHandle handle, Continuation command);

	public void update(DHTContentKey key, DHTUpdateObjectMessage update, Continuation command);
	
	/**
	 * get the nodeHandle of the local Past node
	 * 
	 * @return the nodehandle
	 */
	public NodeHandle getLocalNodeHandle();

	/**
	 * Returns the number of replicas used in this Past
	 * 
	 * @return the number of replicas for each object
	 */
	public int getReplicationFactor();

	public Environment getEnvironment();

	/**
	 * @return
	 */
	public String getInstance();

	public void setContentDeserializer(DHTContentDeserializer deserializer, 
			DHTDifferenceDeserializer differenceDeserializer);

	public void setContentHandleDeserializer(
			DHTContentHandleDeserializer deserializer);

	public Endpoint getEndpoint();

}
